package com.zlc.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zlc.common.common.constant.DeptTypeEnum;
import com.zlc.common.common.service.AutowiredService;
import com.zlc.common.core.dept.mapper.MayanPlatDeptMapper;
import com.zlc.common.core.dept.model.vo.MayanPlatDeptVo;
import com.zlc.common.core.dept.service.MayanPlatDeptService;
import com.zlc.common.core.position.model.entity.MayanPlatDeptPosition;
import com.zlc.common.core.position.model.entity.MayanPlatPositionUser;
import com.zlc.common.core.position.model.vo.MayanPlatDeptPositionVo;
import com.zlc.common.core.position.model.vo.MayanPlatPositionUserVo;
import com.zlc.common.core.position.model.vo.MayanPlatPositionVo;
import com.zlc.common.core.role.model.vo.MayanPlatRoleVo;
import com.zlc.common.core.user.model.vo.MayanPlatUserVo;
import com.zlc.common.util.AssertUtils;
import com.zlc.common.util.BeanCopyUtils;
import com.zlc.common.util.PinyinUtils;
import com.zlc.common.util.PlatUtils;
import com.zlc.common.model.dept.DeptUserVo;
import com.zlc.common.model.dept.DeptVo;
import com.zlc.common.model.position.PositionUserVo;
import com.zlc.common.model.role.UserRoleVo;
import com.zlc.common.model.user.UserInfo;
import com.zlc.platform.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.zlc.common.common.constant.PlatConstant.DEPT_ROOT_ID;


@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class DeptServiceImpl extends AutowiredService implements DeptService {

    @Override
    public void addDept(MayanPlatDeptVo deptVo) {
        String parentDeptId = deptVo.getParentDeptId();
        String deptName = deptVo.getDeptName();
        //生成部门编码
        String deptCode = deptCode(deptName,deptVo.getDeptCode());
        //生成部门等级
        Integer deptLevel = initDeptLevel(parentDeptId);
        deptVo.setDeptLevel(deptLevel);
        deptVo.setDeptCode(deptCode);
        if(ObjectUtils.isEmpty(deptVo.getOrder())){
            deptVo.setOrder(0L);
        }
        //部门编号
        String deptNo = deptVo.getDeptNo();
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptNo),"部门编号不可为空");
        MayanPlatDeptVo platDeptVo = mayanPlatDeptService.getByDeptNo(deptNo);
        AssertUtils.isTrue(ObjectUtils.isEmpty(platDeptVo),"部门编号"+deptNo+"已存在");
        //部门类型
        String deptType = deptVo.getDeptType();
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptType),"部门类型不可为空");
        DeptTypeEnum typeEnum = DeptTypeEnum.deptType(deptType);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(typeEnum),"部门类型错误");

        deptVo.setDeptId(PlatUtils.uuid());
        mayanPlatDeptService.saveVo(deptVo);
    }


    private String deptCode(String deptName,String deptCode){
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptName),"部门名称不可为空");
        if(!ObjectUtils.isEmpty(deptCode)){
            MayanPlatDeptVo platDeptVo = mayanPlatDeptService.getByDeptCode(deptCode);
            AssertUtils.isTrue(ObjectUtils.isEmpty(platDeptVo),"部门编码"+deptCode+"已存在");
            return deptCode;
        }
        StringBuilder builder = new StringBuilder();
        char[] chars = deptName.toCharArray();
        for (char c : chars) {
            String v = String.valueOf(c);
            try {
                String pinyin = PinyinUtils.pinyin(v);
                v = pinyin.substring(0, 1).toUpperCase();
            } catch (Exception e) {
            }
            builder.append(v);
        }
        deptCode = builder.toString();
        MayanPlatDeptVo platDeptVo = mayanPlatDeptService.getByDeptCode(deptCode);
        int index = 1;
        while(!ObjectUtils.isEmpty(platDeptVo)){
            String newDeptCode = deptCode + index;
            platDeptVo = mayanPlatDeptService.getByDeptCode(newDeptCode);
            if(ObjectUtils.isEmpty(platDeptVo)){
                deptCode = newDeptCode;
            }
        }
        return deptCode;
    }

    private int initDeptLevel(String parentDeptId){
        if (DEPT_ROOT_ID.equals(parentDeptId)) {
            return 1;
        }
        MayanPlatDeptVo deptVo = mayanPlatDeptService.getByDeptId(parentDeptId);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptVo),"父部门不存在");
        return deptVo.getDeptLevel() + 1;
    }

    @Override
    public void updateDept(MayanPlatDeptVo deptVo) {
        String deptId = deptVo.getDeptId();
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptId),"部门ID不可为空");
        MayanPlatDeptVo platDeptVo = mayanPlatDeptService.getByDeptId(deptId);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(platDeptVo),"修改的记录不存在");

        //部门类型
        String deptType = deptVo.getDeptType();
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptType),"部门类型不可为空");
        DeptTypeEnum typeEnum = DeptTypeEnum.deptType(deptType);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(typeEnum),"部门类型错误");

        platDeptVo.setDeptType(deptType);
        platDeptVo.setDeptName(deptVo.getDeptName());
        mayanPlatDeptService.saveVo(platDeptVo);
    }

    @Override
    public MayanPlatDeptVo queryOne(String deptId) {
        MayanPlatDeptVo deptVo = mayanPlatDeptService.getByDeptId(deptId);
        if(!ObjectUtils.isEmpty(deptVo.getParentDeptId())){
            MayanPlatDeptVo parentDept = mayanPlatDeptService.getByDeptId(deptVo.getParentDeptId());
            if(!ObjectUtils.isEmpty(parentDept)){
                deptVo.setParentDeptName(parentDept.getDeptName());
            }
        }
        return deptVo;
    }

    @Override
    public DeptVo queryDeptVo() {
        DeptVo root = new DeptVo();
        root.setDeptId(DEPT_ROOT_ID);
        //下层组织
        List<DeptVo> childs = new ArrayList<>();
        //所有组织
        List<MayanPlatDeptVo> deptVos = mayanPlatDeptService.queryVoList(new LambdaQueryWrapper<>());
        //所有根组织
        List<MayanPlatDeptVo> rootDeptVos = deptVos.stream().filter(d -> DEPT_ROOT_ID.equals(d.getParentDeptId())).collect(Collectors.toList());
        for(MayanPlatDeptVo deptVo : rootDeptVos){
            DeptVo parent = BeanCopyUtils.copyObj(deptVo,DeptVo.class);
            initTreeDeptVo(parent,deptVos);
            childs.add(parent);
        }
        root.setChild(childs);
        return root;
    }

    private void initTreeDeptVo(DeptVo parentDept,List<MayanPlatDeptVo> allDept){
        List<MayanPlatDeptVo> childs = allDept.stream().filter(a -> a.getParentDeptId() != null && a.getParentDeptId().equals(parentDept.getDeptId()))
                .collect(Collectors.toList());
        List<DeptVo> childVos = new ArrayList<>();
        for(MayanPlatDeptVo child : childs){
            DeptVo childVo = BeanCopyUtils.copyObj(child,DeptVo.class);
            initTreeDeptVo(childVo,allDept);
            if(ObjectUtils.isEmpty(childVo.getOrder())){
                childVo.setOrder(0L);
            }
            childVos.add(childVo);
        }
        childVos.sort(Comparator.comparing(DeptVo::getOrder));
        parentDept.setChild(childVos);
    }

    @Override
    public void addDeptPosition(MayanPlatDeptPositionVo deptPositionVo) {
        String positionCode = deptPositionVo.getPositionCode();
        String deptCode = deptPositionVo.getDeptCode();
        MayanPlatPositionVo positionVo = mayanPlatPositionService.getByPositionCode(positionCode);
        MayanPlatDeptVo deptVo = mayanPlatDeptService.getByDeptCode(deptCode);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(positionVo),"岗位code不存在");
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptVo),"部门code不存在");
        MayanPlatDeptPositionVo oldRecordVo = mayanPlatDeptPositionService.getByPositionCodeAndDeptCode(positionCode, deptCode);
        if(ObjectUtils.isEmpty(oldRecordVo)){
            mayanPlatDeptPositionService.saveVo(deptPositionVo);
        }
    }

    @Override
    public void removeDeptPosition(String relateId) {
        MayanPlatDeptPosition deptPosition = mayanPlatDeptPositionService.getById(relateId);
        if(ObjectUtils.isEmpty(deptPosition)){
            return;
        }
        String positionCode = deptPosition.getPositionCode();
        String deptCode = deptPosition.getDeptCode();
        LambdaQueryWrapper<MayanPlatPositionUser> wrapper = mayanPlatPositionUserService.wrapper();
        wrapper.eq(MayanPlatPositionUser::getDeptCode,deptCode);
        wrapper.eq(MayanPlatPositionUser::getPositionCode,positionCode);
        List<MayanPlatPositionUserVo> positionUserVos = mayanPlatPositionUserService.queryVoList(wrapper);
        if(!ObjectUtils.isEmpty(positionUserVos)){
            List<String> ids = positionUserVos.stream().map(MayanPlatPositionUserVo::getId).collect(Collectors.toList());
            mayanPlatPositionUserMapper.deleteBatchIds(ids);
        }
        mayanPlatDeptPositionService.removeById(relateId);
    }

    @Override
    public List<MayanPlatPositionVo> queryDeptPositions(String deptCode) {
        return mayanPlatDeptPositionMapper.queryByDeptCode(deptCode);
    }

    @Override
    public void addDeptPositionUser(MayanPlatPositionUserVo positionUserVo) {
        String deptCode = positionUserVo.getDeptCode();
        String positionCode = positionUserVo.getPositionCode();
        String userAccount = positionUserVo.getUserAccount();
        MayanPlatPositionVo positionVo = mayanPlatPositionService.getByPositionCode(positionCode);
        MayanPlatDeptVo deptVo = mayanPlatDeptService.getByDeptCode(deptCode);
        MayanPlatUserVo userVo = mayanPlatUserService.queryByUserAccount(userAccount);
        AssertUtils.isTrue(!ObjectUtils.isEmpty(positionVo),"岗位code不存在");
        AssertUtils.isTrue(!ObjectUtils.isEmpty(deptVo),"部门code不存在");
        AssertUtils.isTrue(!ObjectUtils.isEmpty(userVo),"员工不存在");
        MayanPlatPositionUserVo oldRecordVo = mayanPlatPositionUserService.getByPositionCodeAndDeptCode(positionCode, deptCode,userAccount);
        if(ObjectUtils.isEmpty(oldRecordVo)){
            mayanPlatPositionUserService.saveVo(positionUserVo);
        }
    }

    @Override
    public void removeDeptPositionUser(String relateId) {
        mayanPlatPositionUserService.removeById(relateId);
    }

    @Override
    public List<MayanPlatUserVo> queryPositionUsers(String deptCode, String positionCode) {
        return mayanPlatPositionUserMapper.queryByDeptCodeAndPositionCode(deptCode,positionCode);
    }

    @Autowired
    private MayanPlatDeptService mayanPlatDeptService;
    @Override
    public List<MayanPlatUserVo> queryDeptUsers(String deptCode) {
        List<MayanPlatDeptVo> allDepts = mayanPlatDeptService.getChildDept(deptCode);
        if(ObjectUtils.isEmpty(allDepts)){
            return new ArrayList<>();
        }
        List<String> deptCodes = allDepts.stream().map(MayanPlatDeptVo::getDeptCode).collect(Collectors.toList());
        //查询部门下所有岗位
        return mayanPlatPositionUserMapper.queryUserByDeptCode(deptCodes);
    }



    @Override
    public List<PositionUserVo> getPositionByAccount(String account) {
        //返回值
        List<PositionUserVo> result = new ArrayList<>();
        //查询关联岗位
        LambdaQueryWrapper<MayanPlatPositionUser> wrapper = mayanPlatPositionUserService.wrapper();
        wrapper.eq(MayanPlatPositionUser::getUserAccount,account);
        List<MayanPlatPositionUserVo> positionUserVos = mayanPlatPositionUserService.queryVoList(wrapper);
        if(!ObjectUtils.isEmpty(positionUserVos)){
            for(MayanPlatPositionUserVo positionUserVo : positionUserVos){
                PositionUserVo userVo = new PositionUserVo();
                String positionCode = positionUserVo.getPositionCode();
                String deptCode = positionUserVo.getDeptCode();
                if(!ObjectUtils.isEmpty(positionCode)) {
                    MayanPlatPositionVo positionVo = mayanPlatPositionService.getByPositionCode(positionCode);
                    if(!ObjectUtils.isEmpty(positionVo)) {
                        userVo.setPositionCode(positionCode);
                        userVo.setPositionName(positionVo.getPositionName());
                        MayanPlatRoleVo roleVo = mayanPlatRoleService.getByRoleCode(positionVo.getRoleCode());
                        if (!ObjectUtils.isEmpty(roleVo)) {
                            userVo.setRoleCode(roleVo.getRoleCode());
                            userVo.setRoleName(roleVo.getRoleName());
                        }
                    }
                }
                if(!ObjectUtils.isEmpty(deptCode)){
                    MayanPlatDeptVo deptVo = mayanPlatDeptService.getByDeptCode(deptCode);
                    if(!ObjectUtils.isEmpty(deptVo)) {
                        userVo.setDeptCode(deptCode);
                        userVo.setDeptName(deptVo.getDeptName());
                    }
                }

                if(!ObjectUtils.isEmpty(userVo.getDeptCode()) && !ObjectUtils.isEmpty(userVo.getPositionCode())
                               && !ObjectUtils.isEmpty(userVo.getRoleCode())){
                    result.add(userVo);
                }
            }
        }
        return result;
    }

    @Override
    public void loadUserInfo(UserInfo userInfo) {
        //部门信息
        List<DeptUserVo> depts = new ArrayList<>();
        //角色信息
        List<UserRoleVo> roles = new ArrayList<>();
        //全部岗位信息
        List<PositionUserVo> positionUserVos = getPositionByAccount(userInfo.getUserAccount());
        if(!ObjectUtils.isEmpty(positionUserVos)) {
            positionUserVos.forEach(f-> {
                DeptUserVo deptUserVo = new DeptUserVo();
                deptUserVo.setDeptCode(f.getDeptCode());
                deptUserVo.setDeptName(f.getDeptName());
                if(depts.stream().noneMatch(d->f.getDeptCode().equals(d.getDeptCode()))){
                    depts.add(deptUserVo);
                }
                UserRoleVo userRoleVo = new UserRoleVo();
                userRoleVo.setRoleCode(f.getRoleCode());
                userRoleVo.setRoleName(f.getRoleName());
                if(roles.stream().noneMatch(d->f.getRoleCode().equals(d.getRoleCode()))){
                    roles.add(userRoleVo);
                }
            });
        }
        userInfo.setDepts(depts);
        userInfo.setRoles(roles);
        userInfo.setPositions(positionUserVos);
    }
}
